from comment.models.user import User
from flask_restful import Resource
from flask import current_app,request,g
from comment.utils.sms_send import send_code
import random
import json
from comment.utils.limiter import limiter as lmt
from . import constants
from flask_limiter.util import get_remote_address
from comment.utils.shopping_redis import redis_client
from flask_restful.reqparse import RequestParser
from comment.utils import parser
from comment.models import db
from comment.utils.tokens_pyjwt import generrate_tokens, verify_tokens
from comment.utils.decorators import login_required


class  Shopping_User(Resource):
    '''
    加上登录的拦截
    '''
    method_decorators = {
        'get':[login_required],
        'post':[login_required]

    }

    def get(self):#测试  当前get必须让用户登录之后才能访问
        current_app.logger.info('我的测试日志')
        return {"hello":"测试"}
    def post(self):
        return {'hello':'post 测试'}

    def put(self):
        return {'hello':'put 测试'}


class User_SMS(Resource):
    '''
    发送验证码的短信
    '''
    error_message = 'to many requests'
    decorators = [
        #三个参数  参数1 限流的速率 参数2 key_func 参数三 超出限制之后的提示信息
        lmt.limit(constants.LIMIT_SMS_CODE_BY_MOBILE,
                  key_func=lambda :request.args['phone'],
                  error_message = error_message),
        lmt.limit(constants.LIMIT_SMS_CODE_BY_IP,
                  key_func=get_remote_address,
                  error_message=error_message)
    ]

    def get(self):
       phone =  request.args.get('phone').strip()
       code = random.randint(1000,9999)
       result = send_code(phone,str(code))#返回的是json的字符串
       result = json.loads(result)#把json变成字典
       #result 往里面添加手机号码
       result['phone'] = phone

       #短信验证码发送成功之后 还需把验证码存放到redis数据库中 以便下次验证 验证码的时效为五分钟
       redis_client.setex('shopping:code:{}'.format(phone),constants.SMS_CODE_EXPIRES,code)#参数1 手机号  参数2 时效 参数3验证码

       return result


class AuthorizationCodeResource(Resource):
    '''
    提交手机号和验证码 开始验证
    '''
    def post(self):
        rp = RequestParser()
        rp.add_argument('phone',type=parser.mobile,required = True)
        rp.add_argument('code',type=parser.regex(r'^\d{4}$'),required = True)
        args = rp.parse_args()
        phone = args.phone
        code = args.code

        #从redis数据库中得到之钱保存的验证码
        key = 'shopping:code:{}'.format(phone)
        try:
            real_code = redis_client.get(key) #从redis中返回的是字节数据
        except ConnectionError as e:
            current_app.logger.error(e)
            return {'message':'redis db connect error.'},400

        #开始校验
        if not real_code or real_code.decode() != code:
            return {'message':'Invalid code.'},400

        return {'phone':phone,'msg':'code success.'}





class RegisterUserResource(Resource):
    '''
    填写账号信息，完成用户的注册
    '''
    def post(self):
        rp = RequestParser()
        rp.add_argument('phone',type=parser.mobile,required = True)
        rp.add_argument('username', required=True)
        rp.add_argument('password', required=True)
        rp.add_argument('email',type=parser.email,required=True)
        args = rp.parse_args()
        username = args.username
        password = args.password
        phone = args.phone
        email = args.email

        #验证用户名是否唯一  ：先从mysql数据库中根据当前用户名查询
        u =  User.query.filter(User.username==username).first()
        if u:#用户名已经存在
            current_app.logger.info("{}:用户名已经存在，请换一个".format(username))
            return {'message':'The username already exists.'},400
        #把用户信息保存到数据库中

        u = User(username=username,pwd = password,phone=phone,email=email,status=0)
        db.session.add(u)
        db.session.commit()
        return {'msg':'ok'}


class UserLoginResource(Resource):
    '''
    登录
    '''
    def post(self):
        username = request.form.get('username')
        passoword = request.form.get('password')

        if not all([username,passoword]):#判断用户名和密码是否为空
            return {'message':'数据不完整'},401
        user = User.query.filter(User.username == username).first()
        if user:
            if user.check_password(passoword):
                token = generrate_tokens(user.id)
                #必须把登录成功之后的用户 id得到token
                current_app.logger.info(verify_tokens(token))
                return {'msg':'Login Success','token':token,'username':username},200
        return {'message':'用户名或者密码错误.'},400


class UserLoginOutResource(Resource):
    '''
    退出登录
    '''
    def post(self):
        if g.user_id:
            g.user_id = None
        return {'msg':'退出登录'}

class IsExist(Resource):
    '''
    验证手机号是否可以注册
    '''
    def post(self):
        phone = request.form.get('phone')
        user = User.query.filter(User.phone==phone).first()
        if user:
            return {'isExist': True,'message':'此手机号码已经注册','code':203}
        return {"msg":'手机号可以注册'}
